
use std::collections::HashMap;

pub fn test() {
    println!("hash map 练习.");

    let mut scores = HashMap::new();

    scores.insert(String::from("Melody"), 98);
    scores.insert(String::from("Linxq"), 95);
    println!("scores:{:?}", scores);
    let res = scores.get("Melody");
    match res {
        Some(v) => println!("成绩：{}", v),
        None => println!("名字不存在"),
    }
    // entry() 只在键没有对应值时插入，返回 Entry 枚举
    // Entry 的 or_insert 方法在键对应的值存在时就返回这个值的 Entry，如果不存在则将参数作为新值插入并返回修改过的 Entry。
    scores.entry(String::from("Linxq")).or_insert(67);
    println!("{:?}", scores);


    
    // 使用一个元组的 vector 的 collect 方法，其中每个元组包含一个键值对。
    // TODO: 实际中尽量不要使用这种方法！！！
    let teams = vec![String::from("Blue"), String::from("Yellow")];
    let inits = vec![10, 50];
    // zip 方法来创建一个元组的 vector,collect 方法将这个元组 vector 转换成一个 HashMap
    // 这里类型会是：HashMap<&String, &i32>
    let scores: HashMap<_,_> = teams.iter().zip(inits.iter()).collect();
    for (k, v) in scores {
        println!("k:{}, v:{}", k, v);
    }

    // TODO: 下面一行不能使用，会发生hashmap中键值的所有权转换；这是由于collect()产生的hashmap键值类型是 &str.
    // let res = maps.get(&"Bolue");

    let text = "Melody is a good baby, also is a good girl.";
    let mut words = HashMap::new();
    for word in text.split_whitespace() {
        // or_insert() 返回 &mut V
        let counter = words.entry(word).or_insert(0);
        *counter += 1;
    }
    println!("words:{:?}", words);

    std_test();
}

// 来源于标准库文档的练习
// file:///D:/rust/rustup/toolchains/stable-x86_64-pc-windows-msvc/share/doc/rust/html/std/collections/hash_map/struct.HashMap.html
fn std_test() {
    // 类型会是: HashMap<String, String>
    let mut book_reviews = HashMap::new();

    // Review some books.
    book_reviews.insert(
        "Adventures of Huckleberry Finn".to_string(),
        "My favorite book.".to_string(),
    );
    book_reviews.insert(
        "Grimms' Fairy Tales".to_string(),
        "Masterpiece.".to_string(),
    );
    book_reviews.insert(
        "Pride and Prejudice".to_string(),
        "Very enjoyable.".to_string(),
    );
    book_reviews.insert(
        "The Adventures of Sherlock Holmes".to_string(),
        "Eye lyked it alot.".to_string(),
    );

    if !book_reviews.contains_key("Les Misérables") {
        println!("We've got {} reviews, but Les Misérables ain't one.", book_reviews.len());
    }

    book_reviews.remove("The Adventures of Sherlock Holmes");
    println!("{:?}", book_reviews);

    // 查找
    let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
    for &book in &to_find {
        match book_reviews.get(book) {
            Some(review) => println!("{}: {}", book, review),
            None => println!("{} is note reviewed.", book),
        }
    }
}